#pragma once


#include "fxcc/core/graph/opengl3/pch.h"

namespace fxcc
{
	namespace graph
	{
		namespace opengl3
		{
			struct FXCC_API Buffer
			{
				unsigned int m_Id;
				unsigned int m_Target;

				void* MapBuffer(int access = GL_READ_ONLY)
				{
					return glMapBuffer(m_Target, access);
				}
				template<typename T>
				T* MapData(int access = GL_READ_ONLY)
				{
					return reinterpret_cast<T*>(MapBuffer(access));
				}
				void MemoryBarrier()
				{
					glMemoryBarrier(m_Target);
				}

				void UnMap()
				{
					glUnmapBuffer(m_Target);
				}
				Buffer(const unsigned int target) :m_Target(target)
				{
					Create();
				}
				void Bind() const
				{
					glBindBuffer(GetTarget(), m_Id);

				}
				void GetBufferSubData(int offset, int bufferSize, void* data)
				{
					glGetBufferSubData(GetTarget(), 0, bufferSize, data);

				}
				template<typename T>
				void GetBufferSubDataType(std::vector<T>& ts)
				{
					GetBufferSubData(0, ts.size() * sizeof(float), ts.data());

				}
				void BufferDataBase(unsigned int binding) const
				{
					glBindBufferBase(GetTarget(), binding, m_Id);

				}
				void BufferData(const size_t& sz, const void* header, unsigned int usage = GL_STATIC_DRAW)
				{
					glBufferData(GetTarget(), sz, header, usage);
				}
				unsigned int GetTarget() const
				{
					return m_Target;
				}

				template<typename T>
				void BufferData(const std::vector<T>& ts, unsigned int usage = GL_STATIC_DRAW)
				{
					BufferData(ts.size() * sizeof(T), &ts[0], usage);
				}
				void Create()
				{
					glDeleteBuffers(1, &m_Id);
					glGenBuffers(1, &m_Id);
				}
				void Delete()
				{
					glDeleteBuffers(1, &m_Id);
				}

				virtual ~Buffer()
				{
					Delete();
				}

			};
		};

	};
};